package com.spic.business.utils;

import org.apache.commons.io.FileUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ZIPUtil {
    public static void downfilelist(HttpServletResponse response,List<String> urls, String path) {
        List<File> fileList = new ArrayList<>();
        for (String url : urls) {
            fileList.add(new File(url));
        }
        try {

            File zipFile = zipFiles(fileList, path, Getfilesavename());


            // 将文件写出
            writeOut(response, zipFile);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static String Getfilesavename() {
        ///取到当前时间的年、月、日、分、秒和毫秒的值，并使用字符串格式把它们组合成一个字符串
        String fileTime = new SimpleDateFormat("yyMMddHHmmss").format(new Date(System.currentTimeMillis()));

        String filesavename = fileTime + GetRandomint() + ".zip";
        return filesavename;
    }


    private static String GetRandomint() {
        SecureRandom random = null;
        try {
            random = SecureRandom.getInstance("SHA1PRNG");
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block

        }


        //系统将确定在所请求的包中是否有算法实现；如果没有，则抛出异常。

        return random.nextInt() + "";    //产生一个小于10000的随机正整数
    }

    // 批量文件压缩成zip包
    private static File zipFiles(List<File> fileList, String zipPath, String zipName) throws IOException {
        // 如果被压缩文件中有重复，会重命名
        Map<String, String> namePathMap = getTransferName(fileList);
        File zipPathFile = new File(zipPath);
        // 文件夹不存在则创建
        if (!zipPathFile.exists()) {
            zipPathFile.mkdirs();
        }
        File zipFile = new File(zipPath + File.separator + zipName);
        if (!zipFile.exists()) {
            zipFile.createNewFile();
        }
        ZipOutputStream zos = null;
        BufferedInputStream bis = null;
        try {
            // 存放的目标文件
            zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile.getPath())));
            Set<String> keySet = namePathMap.keySet();
            ZipEntry zipEntry = null;
            for (String key : keySet) { // key是文件名，value是path
                // 指定源文件
                File sourceFile = new File(namePathMap.get(key));
                bis = new BufferedInputStream(new BufferedInputStream(new FileInputStream(sourceFile)));
                // 创建ZIP实体，并添加进压缩包,指定压缩文件中的文件名
                zipEntry = new ZipEntry(key);
                zos.putNextEntry(zipEntry);
                // 读取待压缩的文件并写进压缩包里
                zos.write(FileUtils.readFileToByteArray(sourceFile));
                if (bis != null) {
                    bis.close();
                }

            }

            zos.flush();
            zos.closeEntry();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭流
            if (bis != null) {
                bis.close();
            }
            if (null != zos) {
                zos.close();
            }
            for (File file:
                    fileList) {
                file.delete();
            }
        }
        return zipFile;

    }

    /**
     * 将文件写出到流 【方法名】{方法的功能/动作描述}
     *
     * @author Fisher
     */
    private static void writeOut(HttpServletResponse response, File zipFile) throws IOException {
        response.reset();
        response.setContentType("application/zip");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + zipFile.getName());
        OutputStream outputStream = response.getOutputStream();
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(zipFile.getPath());
            int len = 0;
            byte[] buffer = new byte[1024];
            while ((len = fis.read(buffer)) > 0) {
                outputStream.write(buffer, 0, len);
            }
            outputStream.flush();

        } finally {
            if (null != fis) {
                fis.close();
            }
            if (null != outputStream) {
                outputStream.close();
            }
            zipFile.delete();
        }
    }

    // 计算压缩包如果已存在重复的名称，则在重复文件后面跟上数字 如: 文件(1).doc,文件(2).doc
    private static Map<String, String> getTransferName(List<File> fileList) {
        if (fileList == null || fileList.size() == 0) {
            return new HashMap<String, String>();
        }
        // key存放文件名，value存放path
        Map<String, String> fileNameMap = new HashMap<>();
        List<String> fileNames = new ArrayList<>();
        for (File file : fileList) {
            // 获取文件名
            String fileName = file.getName();
            int count = 0;

            for (String name : fileNames) {
                if (name != null && name.equals(fileName)) {
                    count++;
                }
            }
            fileNames.add(fileName);
            if (count > 0) {
                int lastIndex = fileName.lastIndexOf('.');
                String name = fileName.substring(0, lastIndex);
                String type = fileName.substring(lastIndex + 1);
                fileName = new StringBuilder().append(name).append("(").append(count).append(")").append(".")
                        .append(type).toString();
                fileNameMap.put(fileName, file.getPath());
            } else {
                fileNameMap.put(fileName, file.getPath());
            }
        }
        return fileNameMap;
    }

}
